#include<typeinfo>
#include<iostream>

struct Shape;
struct Rectangle;
struct Triangle;

bool intersect_rr(Rectangle const * r1, Rectangle const * r2) {
	std::cout << "Intersecting Rectangle x Rectangle" << std::endl;
	return true;
}

bool intersect_tr(Triangle const * r1, Rectangle const * r2) {
	std::cout << "Intersecting Triangle x Rectangle" << std::endl;
	return true;
}

bool intersect_tt(Triangle const * r1, Triangle const * r2) {
	std::cout << "Intersecting Triangle x Triangle" << std::endl;
	return true;
}

struct Shape {
	virtual ~Shape() {}
		
	virtual bool make_intersect(Shape const *) const = 0;
	virtual bool make_intersect(Rectangle const *) const = 0;
	virtual bool make_intersect(Triangle const *) const = 0;
		
};

struct Rectangle : public Shape {
	bool make_intersect(Shape const * s) const  {
		return s -> make_intersect(this);
	}
	bool make_intersect(Triangle const * t) const  {
		return intersect_tr(t, this);
	}
	bool make_intersect(Rectangle const * t) const  {
		return intersect_rr(t, this);
	}
};

struct Triangle : public Shape {
	bool make_intersect(Shape const * s) const  {
		return s -> make_intersect(this);
	}
	bool make_intersect(Triangle const * t) const  {
		return intersect_tt(t, this);
	}
	bool make_intersect(Rectangle const * t) const  {
		return intersect_tr(this, t);
	}
	
};

/*bool intersect(Shape const * s1, Shape const * s2) {
	Rectangle const * r1 = dynamic_cast<Rectangle const *>(s1);
	Rectangle const * r2 = dynamic_cast<Rectangle const *>(s2);
	Triangle const * t1 = dynamic_cast<Triangle const *>(s1);
	Triangle const * t2 = dynamic_cast<Triangle const *>(s2);
	if (r1 != 0) {
		if (r2 != 0)
			return intersect_rr(r1, r2);
		else if (t2 != 0)
			return intersect_tr(t2, r1);
	} else if (t1 != 0) {
		if (r2 != 0)
			return intersect_tr(t1, r2);
		else if (t2 != 0)
			return intersect_tt(t1, t2);
	}
	throw "Unknown shape";
}*/

bool intersect(Shape const * s1, Shape const * s2) {
	return s1 -> make_intersect(s2);
}

int main() {
	Shape * r = new Rectangle();
	Shape * t = new Triangle();
	//Shape * s = new Shape();
	intersect(r, t);
	intersect(t, t);
	intersect(r, r);
	intersect(t, r);
	/*try {
		intersect(s, s);
	} catch (char const * st) {
		std::cout << st << std::endl;
	}*/
}